home *** CD-ROM | disk | FTP | other *** search
/ Aminet 28 / Aminet 28 (1998)(GTI - Schatztruhe)[!][Dec 1998].iso / Aminet / dev / c / dice-3.16.lha / examples / Visual / VCommon / vmenu.c < prev   
C/C++ Source or Header  |  1998-09-27  |  13KB  |  427 lines

  1. #include "project.h"
  2. #ifdef PROJECT_VOPTS
  3.    #include "vopts.h"
  4. #endif
  5. #ifdef PROJECT_VMAKE
  6.    #include "vmake.h"
  7. #endif
  8. #include <proto/gadtools.h>
  9.  
  10. Prototype void enable_menu(void);
  11. Prototype struct Menu *create_menus(struct NewMenu *menulist);
  12. Prototype int layout_menus(struct Menu *menus);
  13. Prototype void free_menus(struct Menu *menus);
  14. Prototype void ghost_menus(void);
  15. Prototype void unghost_menus(void);
  16.  
  17. /***********************************************************************************
  18.  * Procedure: enable_menu
  19.  * Synopsis:  enable_menu();
  20.  * Purpose:   Attach any system defined menus to the current window.
  21.  ***********************************************************************************/
  22. void enable_menu()
  23. {
  24.    int i, level, newlev, count[4];
  25.    struct NewMenu *newmenu;
  26.  
  27.    if (global.window == NULL) return;
  28.  
  29.    /* Let us go through and validate the menu they have constructed */
  30.    level = 0;
  31.    newmenu = global.menuitem;
  32.    for (i = 0; i < MAX_MENU; i++)
  33.    {
  34.       newlev = newmenu[i].nm_Type;
  35.       if (newlev > level)
  36.       {
  37.          level++;
  38.          /* Make sure we are going down only one level */
  39.          if (newmenu[i].nm_Type != level || level > MENU_SUB) return;
  40.          count[level] = 0; /* Initialize our count */
  41.       }
  42.       else if (newlev == level)
  43.       {
  44.          /* Make sure we don't have two TITLES in a row */
  45.          if (level == MENU_MENU) return;
  46.          count[level]++;
  47.       }
  48.       else
  49.       {
  50.          /* We are going up a level.  Validate the counts on the way up */
  51.          if (newlev < MENU_END) return;
  52.          while (level > newlev)
  53.          {
  54.             if (count[level] >= "!\x20\x40\x20"[level])
  55.                return;
  56.             else
  57.                level--;
  58.          }
  59.          /* When we hit the end of the menus, break */
  60.          if (level == 0) break;
  61.          count[level]++;
  62.       }
  63.  
  64.    }
  65.    /* Lastly ensure that they had an END marker */
  66.    if (level) return;
  67.  
  68.    if (!(global.menu = create_menus(newmenu)))
  69.       return;
  70.  
  71.    if (!layout_menus(global.menu))
  72.       return;
  73.  
  74.    SetMenuStrip(global.window, global.menu);
  75. }
  76.  
  77. /***********************************************************************************
  78.  * Procedure: create_menus
  79.  * Synopsis:  Menu = create_menus(NewMenu);
  80.  * Purpose:   Create the appropriate menu structures for a given NewMenu list
  81.  ***********************************************************************************/
  82. struct Menu *create_menus(struct NewMenu *menulist
  83.                          )
  84. {
  85.    int i;
  86.    struct Menu   *retmenu;
  87.    struct XMenu  *thismenu;
  88.    struct XItem  *thisitem;
  89.    static struct Image sep_image = {5, 1, 1000, 2,0, NULL, 0,0, NULL};
  90.  
  91.  
  92.    if (GadToolsBase != NULL)
  93.    {
  94.       struct TagItem taglist[2];
  95.  
  96.       taglist[0].ti_Tag = GTMN_FrontPen;
  97.       taglist[0].ti_Data = 0;
  98.       taglist[1].ti_Tag = TAG_DONE;
  99.  
  100.       return(CreateMenusA(menulist, taglist));
  101.    }
  102.  
  103.    /* We don't have GadTools around to do the work for us, so just create the */
  104.    /* Menu structures directly.                                               */
  105.  
  106.    retmenu = NULL;  /* Default to giving them NOTHING */
  107.  
  108.    for (i = 0; i < MAX_MENU; i++)
  109.    {
  110.       switch (menulist[i].nm_Type)
  111.       {
  112.          case NM_TITLE:
  113.             {
  114.                struct XMenu  *newmenu;
  115.  
  116.                newmenu = (struct XMenu *)get_mem(sizeof(struct XMenu));
  117.                if (newmenu == NULL)
  118.                {
  119.                   free_menus(retmenu);
  120.                   return(NULL);
  121.                }
  122.  
  123.                /* Link the menu structure onto the list of other menus */
  124.                if (retmenu == NULL)
  125.                   retmenu = &newmenu->menu;
  126.                else
  127.                   thismenu->menu.NextMenu = &newmenu->menu;
  128.  
  129.                thismenu = newmenu;
  130.             }
  131.  
  132.             thismenu->menu.Flags    = MENUENABLED;
  133.             thismenu->menu.MenuName = (BYTE *)menulist[i].nm_Label;
  134.             thismenu->userdata      = menulist[i].nm_UserData;
  135.             thismenu->image         = sep_image;
  136.             break;
  137.  
  138.         case NM_ITEM:
  139.             if (thismenu == NULL) return(NULL);
  140.  
  141.             {
  142.                struct XItem  *newitem;
  143.  
  144.                newitem = (struct XItem *)get_mem(sizeof(struct XItem));
  145.                if (newitem == NULL)
  146.                {
  147.                   free_menus(retmenu);
  148.                   return(NULL);
  149.                }
  150.                if (thismenu->menu.FirstItem == NULL)
  151.                   thismenu->menu.FirstItem = &newitem->item;
  152.                else
  153.                   thisitem->item.NextItem  = &newitem->item;
  154.                thisitem = newitem;
  155.             }
  156.  
  157.             if (menulist[i].nm_Label == NM_BARLABEL)
  158.             {
  159.                thisitem->item.Flags        = 0;
  160.                thisitem->item.ItemFill     = &thismenu->image;
  161.             }
  162.             else
  163.             {
  164.                /* fill in the intuitext with some reasonable defaults */
  165.  
  166.                thisitem->itext.FrontPen    = 0;
  167.                thisitem->itext.DrawMode    = JAM1;
  168.                thisitem->itext.LeftEdge    = 5;
  169.                thisitem->itext.TopEdge     = 1;
  170.                thisitem->itext.ITextFont   = &global.ri.TextAttr;
  171.                thisitem->itext.IText       = menulist[i].nm_Label;
  172.  
  173.                thisitem->item.Flags        = ITEMTEXT|ITEMENABLED|HIGHCOMP;
  174.                thisitem->item.ItemFill     = (APTR)&thisitem->itext;
  175.  
  176.                if (menulist[i].nm_CommKey)
  177.                {
  178.                   thisitem->item.Command   = *menulist[i].nm_CommKey;
  179.                   thisitem->item.Flags    |= COMMSEQ;
  180.                }
  181.             }
  182.             thisitem->userdata = menulist[i].nm_UserData;
  183.             break;
  184.  
  185.          case NM_END:
  186.              return(retmenu);
  187.       }
  188.    }
  189.    return(retmenu);
  190. }
  191.  
  192. /***********************************************************************************
  193.  * Procedure: layout_menus
  194.  * Synopsis:  rc = layout_menus(Menu);
  195.  * Purpose:   Lays out a menu given the current global information
  196.  ***********************************************************************************/
  197. int layout_menus(struct Menu *menus)
  198. {
  199.    struct XMenu     *menu;
  200.    struct XItem     *item;
  201.    int              xpos;
  202.  
  203.    if (GadToolsBase != NULL)
  204.    {
  205.       struct VisualInfo *vi;
  206.       struct TagItem taglist;
  207.       int rc;
  208.  
  209.       taglist.ti_Tag = TAG_DONE;
  210.  
  211.       rc = 0;
  212.       if ((vi = GetVisualInfoA(global.window->WScreen, &taglist)))
  213.       {
  214.          rc = LayoutMenusA(global.menu, vi, &taglist);
  215.          FreeVisualInfo(vi);
  216.       }
  217.       return(rc);
  218.    }
  219.  
  220.    xpos = VBAR;
  221.  
  222.    for (menu = (struct XMenu *)menus; menu;
  223.         menu = (struct XMenu *)menu->menu.NextMenu)
  224.    {
  225.       int width, ypos;
  226.  
  227.       /* set the x position of the menu to the next available position.
  228.        * Set the menu width based on the size of the text.
  229.        */
  230.  
  231.       menu->menu.LeftEdge = xpos;
  232.       menu->menu.Width    = text_width(menu->menu.MenuName) + DVBAR;
  233.  
  234.       /* set the initial item y-position to just below the title bar */
  235.  
  236.       ypos = 0;
  237.  
  238.       /* walk through the list of items for the first pass. The object
  239.        * is to find the width of the largest item. We will also set
  240.        * the y-position of each item on this pass.
  241.        */
  242.  
  243.       width = menu->menu.Width;    /* make items at least as big as menu */
  244.  
  245.       for (item = (struct XItem *)menu->menu.FirstItem;
  246.            item;
  247.            item = (struct XItem *)item->item.NextItem)
  248.       {
  249.          int  iwidth;
  250.  
  251.          /* set the y-position of the item to the next available. Also,
  252.           * put the item just to the left of the menu. You can make
  253.           * this number zero if you prefer.
  254.           */
  255.  
  256.          item->item.TopEdge = ypos;
  257.          item->item.LeftEdge = -VBAR;
  258.  
  259.          /* if it's a text item, see how big it is. */
  260.  
  261.          if (item->item.Flags & ITEMTEXT)
  262.          {
  263.             struct IntuiText *itext;
  264.  
  265.             itext = (struct IntuiText *)item->item.ItemFill;
  266.  
  267.             /* the height is just the font height + 2. The width is
  268.              * based on the string pixel width.
  269.              */
  270.  
  271.             item->item.Height = global.ri.FontSize + 2;
  272.             iwidth = text_width(itext->IText) + 10;
  273.  
  274.             /* i